
# coding: utf-8
import io
import cv2
import numpy as np
from PIL import Image, ImageFilter, ImageEnhance


def binarizing(im, threshold):
    pixdata = im.load()

    w, h = im.size
    for j in range(h):
        for i in range(w):
            if pixdata[i, j] < threshold:
                pixdata[i, j] = 0
            else:
                pixdata[i, j] = 255
    return im


def denoising(im):
    pixdata = im.load()
    w, h = im.size
    for j in range(1, h - 1):
        for i in range(1, w - 1):
            count = 0
            if pixdata[i, j - 1] > 245:
                count += 1
            if pixdata[i, j + 1] > 245:
                count += 1
            if pixdata[i + 1, j] > 245:
                count += 1
            if pixdata[i - 1, j] > 245:
                count += 1
            if count > 2:
                pixdata[i, j] = 255
    return im


def buf_to_img(buf):
    f = io.StringIO(buf)
    return Image.open(f)


def convert_img_main(buf):
    img = buf_to_img(buf)
    img = img.filter(ImageFilter.MedianFilter(1))  # 对于输入图像的每个像素点，该滤波器从（size，size）的区域中拷贝中值对应的像素值存储到输出图像中
    img = ImageEnhance.Contrast(img).enhance(
        1.5)  # enhance()的参数factor决定着图像的对比度情况。从0.1到0.5，再到0.8，2.0，图像的对比度依次增大.0.0为纯灰色图像;1.0为保持原始
    img = img.convert('L')  # 灰度图转换
    img = denoising(img)  # 图片去噪
    img = binarizing(img, 200)  # 图片二值化
    return img


def url_to_image(buf):
    # download the image, convert it to a NumPy array, and then read
    # it into OpenCV format
    image = np.asarray(bytearray(buf), dtype="uint8")
    image = cv2.imdecode(image, cv2.IMREAD_COLOR)

    # return the image
    return image


def highlight(image):
    if False:
        print('************average light********')
        print(sum(image[0])/len(image[0]))
        print('************average light end********')
    if sum(image[0])/len(image[0]) < 220:  # 200
        # new = np.where(image>(255/2),255,image*2)
        dilated_img = cv2.dilate(image, np.ones((7, 7), np.uint8))
        if False:
            cv2.imshow('dilated', dilated_img)
            cv2.waitKey(0)
        bg_img = cv2.medianBlur(dilated_img, 21)
        if False:
            cv2.imshow('median blur', bg_img)
            cv2.waitKey(0)
        diff_img = 255 - cv2.absdiff(image, bg_img)
        if False:
            cv2.imshow('origin vs back diff', diff_img)
            cv2.waitKey(0)
        norm_img = diff_img.copy()  # Needed for 3.x compatibility
        cv2.normalize(diff_img, norm_img, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)
        if False:
            cv2.imshow('first norm', norm_img)
            cv2.waitKey(0)
        _, thr_img = cv2.threshold(norm_img, 230, 0, cv2.THRESH_TRUNC)
        cv2.normalize(thr_img, thr_img, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)
        if False:
            cv2.imshow('second norm', thr_img)
            cv2.waitKey(0)
            cv2.destroyAllWindows()
        # new = norm_img
        new = thr_img
        # sys.exit()
    else:
        new = image
    return new


def pre_img(buf):
    img = url_to_image(buf)
    # img = cv2.imread('D:/workspace/orc/origin/qqqqqqqqqq.png')
    im_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)   # 转换了灰度化
    # blurred = cv2.medianBlur(im_gray, 5)  # 降噪
    # cv2.imshow('1111', im_gray)
    # cv2.waitKey(0)
    # img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, -10)
    # im_at_mean = cv2.adaptiveThreshold(im_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 7, 10)
    # im_at_mean = cv2.adaptiveThreshold(im_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 7, 14)
    # im_at_mean = cv2.adaptiveThreshold(im_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 14)
    # hight, im_at_mean = cv2.threshold(im_gray, 128, 255, cv2.THRESH_BINARY)
    im_at_mean = cv2.adaptiveThreshold(im_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 14)
    # im_at_mean = cv2.cvThreshold(im_gray, 0, 255, cv2.CV_THRESH_BINARY)

    # cv2.imshow('1111', im_at_mean)
    # im_at_mean = highlight(im_gray)
    # cv2.imwrite('D:/workspace/orc/5t/001.jpg', im_at_mean)
    img = Image.fromarray(im_at_mean)
    return img


def rotate_bound(image, angle):
    # grab the dimensions of the image and then determine the
    # center
    (h, w) = image.shape[:2]
    (cX, cY) = (w // 2, h // 2)

    # grab the rotation matrix (applying the negative of the
    # angle to rotate clockwise), then grab the sine and cosine
    # (i.e., the rotation components of the matrix)
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])

    # compute the new bounding dimensions of the image
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))

    # adjust the rotation matrix to take into account translation
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY

    # perform the actual rotation and return the image
    return cv2.warpAffine(image, M, (nW, nH))
